
GLOBAL  read_msw,_lidt
GLOBAL  int_08_hand, int_09_hand, int_0C_hand, int_80_hand, write
GLOBAL	mascaraPIC1,mascaraPIC2,_Cli,_Sti
GLOBAL  debug
GLOBAL  myin, myout
GLOBAL  _DelCursor, _RestoreCursor, _Lights, _Reboot, _Beep, _inb;

EXTERN  int_08
EXTERN	int_09
EXTERN 	int_0C
EXTERN	int_80


SECTION .text


_Cli:
	cli			; limpia flag de interrupciones
	ret

_Sti:

	sti			; habilita interrupciones por flag
	ret

mascaraPIC1:			; Escribe mascara del PIC 1
	push    ebp
        mov     ebp, esp
        mov     ax, [ss:ebp+8]  ; ax = mascara de 16 bits
        out	21h,al
        pop     ebp
        retn

mascaraPIC2:			; Escribe mascara del PIC 2
	push    ebp
        mov     ebp, esp
        mov     ax, [ss:ebp+8]  ; ax = mascara de 16 bits
        out	0A1h,al
        pop     ebp
        retn

read_msw:
        smsw    ax		; Obtiene la Machine Status Word
        retn


_lidt:				; Carga el IDTR
        push    ebp
        mov     ebp, esp
        push    ebx
        mov     ebx, [ss: ebp + 6] ; ds:bx = puntero a IDTR 
	rol	ebx,16		    	
	lidt    [ds: ebx]          ; carga IDTR
        pop     ebx
        pop     ebp
        retn


int_08_hand:					; Handler de INT 8 (Timer tick)
        push    ds
        push    es              ; Se salvan los registros
        pusha                   ; Carga de DS y ES con el valor del selector
        mov     ax, 10h			; a utilizar.
        mov     ds, ax
        mov     es, ax                  
        call    int_08                 
        mov	al,20h			; Envio de EOI generico al PIC
		out	20h,al
		popa                            
        pop     es
        pop     ds
        iret


int_09_hand:				; Handler de INT 9 (Teclado)
        push    ds
        push    es          ; Se salvan los registros
        pusha               ; Carga de DS y ES con el valor del selector
        mov     ax, 10h		
        mov     ds, ax
        mov     es, ax      
        
        mov 	eax, 0		; Limpio ah
        in 		al, 60h		; Puerto de datos del teclado
        push	eax         ; Paso scancode como parametro   
        call    int_09                 
        mov		al,20h		; Envio de EOI generico al PIC
		out		20h,al
		pop 	eax
		
		popa                            
        pop     es
        pop     ds
        iret

int_0B_hand:				; Handler de INT C ( COM 2)
        push    ds
        push    es              ; Se salvan los registros
        pusha                   ; Carga de DS y ES con el valor del selector
        mov     ax, 10h			; a utilizar.
        mov     ds, ax
        mov     es, ax                  
        call    int_0C                 
        mov	al,20h			; Envio de EOI generico al PIC
		out	20h,al
		popa                            
        pop     es
        pop     ds
        iret

int_0C_hand:				; Handler de INT C ( COM 1)
        push    ds
        push    es              ; Se salvan los registros
        pusha                   ; Carga de DS y ES con el valor del selector
        mov     ax, 10h			; a utilizar.
        mov     ds, ax
        mov     es, ax                  
        call    int_0C                 
        mov	al,20h			; Envio de EOI generico al PIC
		out	20h,al
		popa                            
        pop     es
        pop     ds
        iret

int_80_hand:				; Handler de INT 80 ( write)
        
    call _Cli                     
    push    ds
    push    es
    pusha

    push    edx             ; size
    push    ecx             ; buff
    push    ebx             ; fd
    call    int_80
  
    pop     ebx             ;vacio la pila
    pop     edx
    pop     ecx

	;mov	al,20h			; Envio de EOI generico al PIC
	;out	20h,al
	
    popa
    pop     es
    pop     ds
    call _Sti                    
    iret

write:
	push    ebp             ; stack frame
    mov     ebp, esp

    mov     ebx, [ebp+8]    ; fd
    mov     ecx, [ebp+12]   ; buff
    mov     edx, [ebp+16]   ; size

    int     080h

    mov     esp, ebp        
    pop     ebp
    ret
    
    
; Debug para el BOCHS, detiene la ejecucion.
; Para continuar colocar en el BOCHSDBG: set $eax=0

debug:
        push    bp
        mov     bp, sp
        push	ax
		mov     ax, 1
vuelve: cmp	ax, 0
		jne	vuelve
		pop	ax
		pop     bp
        retn

myout:
	push EBP
	mov EBP, ESP
	mov EAX, [EBP+12]
	mov EDX, [EBP+8]
	out DX, Al
	pop EBP
	ret	

myin:
	push EBP
    mov EBP, ESP
	mov EDX, [EBP+8]
	mov ECX, [EBP+12]
	in AL, DX
	mov [ECX], AL
	pop	EBP
	ret


_DelCursor:
     push     ax
     push     dx
     pusha
	 mov	 bx, 0xF00				; Hago desaparecer el cursor
     mov     dx, 0x3D4
     mov     al, 0x0A
     mov     ah, bh
     out     dx, ax
     inc     ax
     mov     ah, bl
     out     dx, ax
     popa
     pop     dx
     pop     ax
     ret


_RestoreCursor:
     push     ax
     push     dx
     pusha
	 mov	 bx, 0xFF0				; Vuelvo a ponerle grosor visible
     mov     dx, 0x3D4
     mov     al, 0x0A
     mov     ah, bh
     out     dx, ax
     inc     ax
     mov     ah, bl
     out     dx, ax
     popa
     pop     dx
     pop     ax
     ret


_Lights:
    push	ebp
	mov		ebp, esp
	mov		al,[EBP+8]
	mov		ah,al

    cli                             ; Deshabilito interrupciones
    mov     al,0edh                 ; Cargo el Set/Reset Mode Indicator
    out     60h,al

l1: in      al,60h                  ; Espero el ACK del 8042
    cmp     al,0fah
    jnz     l1
    mov     al,ah                   ; Mando las nuevas luces
    out     60h,al
l2: in      al,60h                  ; Espero el ACK del 8042
    cmp     al,0fah
    jnz     l2
    sti                             ; habilito interrupciones de nuevo
	pop		ebp
    ret


;Funcion hecha a partir de codigo encontrado en http://www.programmersheaven.com
_Beep:
	push ax
	push cx
	mov al,182
	out 43h,al		; setup for sound
	mov al,255
	out 42h,al		; low part
	mov al,0		; get alarm tone
	out 42h,al		; high part
	in al,61h
	push ax 		; save port value
	or al,3
	out 61h,al		; turn speaker on
	mov cx,00FFh	; get loop count
l:	loop l			; wait around
	pop ax			; restore original port value
	out 61h,al		; turn speaker off
	pop cx
	pop ax
	ret


_Reboot:
	jmp [0FFFFh]


; Codigo de http://www.osdev.org/wiki/Reboot
_inb:		
	push ebp			
    mov ebp, esp
	mov edx, [ebp+8]
	mov eax, 0
	in al, dx
	pop	ebp
	ret

     	